package com.nian.common.lock.redis;

import com.nian.redis.cache.JedisClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;

import java.util.Arrays;

/**
 * 用途：
 * 开发：zhangmj
 * 日期：2020/4/13 0013 17:40
 */
@Slf4j
@Service
public class RedisDistributedLuaLock implements IRedisLock {

    @Autowired
    JedisClient jedisClient;

    private static final DefaultRedisScript<Long> LOCK_SCRIPT;
    private static final DefaultRedisScript<Object> UNLOCK_SCRIPT;
    static {
        // 加载释放锁的脚本
        LOCK_SCRIPT = new DefaultRedisScript<>();
        LOCK_SCRIPT.setScriptSource(new ResourceScriptSource(new ClassPathResource("lock.lua")));
        LOCK_SCRIPT.setResultType(Long.class);
        log.info("redis 分布式锁 获取锁 lua 脚本：{}", LOCK_SCRIPT.getScriptAsString());
        // 加载释放锁的脚本
        UNLOCK_SCRIPT = new DefaultRedisScript<>();
        UNLOCK_SCRIPT.setScriptSource(new ResourceScriptSource(new ClassPathResource("unlock.lua")));
        log.info("redis 分布式锁 释放锁 lua 脚本：{}", UNLOCK_SCRIPT.getScriptAsString());
    }

    @Override
    public boolean lock(String lockName, String requestId) {
        return lock(lockName, requestId, IRedisLock.TIMEOUT);
    }

    @Override
    public boolean lock(String lockName, String requestId, int millisecondsToExpire) {
        Long rs = jedisClient.eval(LOCK_SCRIPT.getScriptAsString(), Arrays.asList(lockName), Arrays.asList(requestId, String.valueOf(millisecondsToExpire/1000)));
        return rs != null && rs == 1L;
    }

    @Override
    public boolean unLock(String lockName, String requestId) {
        jedisClient.eval(UNLOCK_SCRIPT.getScriptAsString(), Arrays.asList(lockName), Arrays.asList(requestId));
        return true;
    }
}
